/**
 * 步骤5测试：查询可用日期（日历扫描，支持翻月，最多3个月）
 */

import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
import { HttpSession } from '../src/main/request/http-session'
import { getPageParser } from '../src/main/automation/page-parser'
import { loadConfig } from '../src/main/config/index'
import { setupLogger } from '../src/main/logger/index'
import { writeFile, mkdir, readFile } from 'node:fs/promises'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const projectRoot = join(__dirname, '..')

const BASE_URL = 'https://abs1.td.gov.hk/tdab2/tdabs_external/AdminServlet_tchinese'
const SNAPSHOT_DIR = join(projectRoot, 'test-steps-snapshots')

async function saveSnapshot(name: string, html: string, metadata: any = {}) {
  await mkdir(SNAPSHOT_DIR, { recursive: true })
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
  const filename = `${timestamp}_step05_${name}.html`
  const filepath = join(SNAPSHOT_DIR, filename)
  await writeFile(filepath, html, 'utf8')
  console.log(`  ✓ 快照已保存: ${filename}`)
  return filepath
}

async function loadStep4Result() {
  const files = await import('node:fs/promises')
  const dir = await files.readdir(SNAPSHOT_DIR)
  
  // 优先查找办事处选择的结果，其次查找电话填写，最后查找身份验证
  let step4Files = dir.filter(f => f.includes('step04_office_select') && f.endsWith('.html')).sort().reverse()
  if (step4Files.length === 0) {
    step4Files = dir.filter(f => f.includes('step04_phone_input') && f.endsWith('.html')).sort().reverse()
  }
  if (step4Files.length === 0) {
    step4Files = dir.filter(f => f.includes('step04_identity_check') && f.endsWith('.html')).sort().reverse()
  }
  
  if (step4Files.length === 0) {
    throw new Error('未找到步骤4的快照文件，请先运行步骤4测试')
  }
  
  const latestFile = join(SNAPSHOT_DIR, step4Files[0])
  const html = await readFile(latestFile, 'utf8')
  const parser = getPageParser()
  const formFields = parser.extractFormFields(html, 'frmAppointment')
  
  return { html, formFields, filepath: latestFile }
}

function checkCalendarPage(html: string): { success: boolean, details: Record<string, boolean>, availableDates: string[] } {
  const parser = getPageParser()
  const datesResult = parser.parseAvailableDates(html)
  const availableDates = datesResult.success && datesResult.data ? datesResult.data : []
  
  const checks = {
    isCalendar: html.includes('cmdGetCalendarAction') || html.includes('onClickDate') || html.includes('calendar-table'),
    hasCalendarHeader: html.includes('calendar-table-header-cell'),
    hasDateLinks: html.includes('onClickDate'),
    hasNextMonth: html.includes('nextMonth') || html.includes('onClickMonth'),
    hasPrevMonth: html.includes('prevMonth') || html.includes('onClickMonth'),
    hasForm: html.includes('form') && html.includes('frmAppointment'),
    hasAvailableDates: availableDates.length > 0,
  }
  
  console.log(`\n📄 日历页面检查`)
  console.log('─'.repeat(60))
  for (const [key, value] of Object.entries(checks)) {
    const icon = value ? '✓' : '✗'
    const label = key.replace(/([A-Z])/g, ' $1').trim()
    console.log(`  ${icon} ${label}`)
  }
  
  console.log(`\n  📅 可用日期数量: ${availableDates.length}`)
  if (availableDates.length > 0) {
    console.log(`  📅 可用日期: ${availableDates.slice(0, 10).join(', ')}${availableDates.length > 10 ? '...' : ''}`)
  }
  
  return { success: checks.isCalendar && checks.hasForm, details: checks, availableDates }
}

// 获取指定年月的日历
async function getCalendarForMonth(
  session: HttpSession,
  baseFields: Record<string, string>,
  year: number,
  month0: number, // 0基月
): Promise<{ html: string, dates: string[] }> {
  const payload: Record<string, string> = {
    ...baseFields,
    storedAppointmentOperation: 'A',
    storedAppointmentCalendarYear: year.toString(),
    storedAppointmentCalendarMonth: month0.toString(),
    storedAppointmentOfficeCode: baseFields.storedAppointmentOfficeCode || 'HKLO',
    timestamp: Date.now().toString(),
  }
  
  const url = `${BASE_URL}?cmd=cmdGetCalendarAction`
  const response = await session.postForm(url, payload, `${BASE_URL}?cmd=cmdGetCalendarAction`)
  
  const parser = getPageParser()
  const datesResult = parser.parseAvailableDates(response.body)
  const dates = datesResult.success && datesResult.data ? datesResult.data : []
  
  return { html: response.body, dates }
}

async function testStep5() {
  console.log('步骤5测试：查询可用日期（日历扫描，支持翻月，最多3个月）')
  console.log('='.repeat(60))
  
  await loadConfig()
  await setupLogger()
  
  // 加载步骤4的结果
  console.log('\n📂 加载步骤4结果...')
  const step4Result = await loadStep4Result()
  const step4Fields = step4Result.formFields.success && step4Result.formFields.data ? step4Result.formFields.data : {}
  console.log(`  从步骤4提取字段数: ${Object.keys(step4Fields).length}`)
  
  const session = new HttpSession()
  
  // 子步骤5.1: 获取当前月日历
  console.log('\n子步骤5.1: 获取当前月日历')
  console.log('─'.repeat(60))
  
  // 如果步骤4已经在日历页，使用当前字段；否则获取日历
  let currentFields = step4Fields
  let currentHtml = step4Result.html
  let isAlreadyCalendar = step4Result.html.includes('onClickDate') || step4Result.html.includes('calendar-table')
  
  if (!isAlreadyCalendar) {
    const currentDate = new Date()
    const year = currentDate.getFullYear()
    const month0 = currentDate.getMonth()
    
    console.log(`  获取 ${year}年${month0 + 1}月 日历`)
    const calendarResult = await getCalendarForMonth(session, currentFields, year, month0)
    currentHtml = calendarResult.html
    
    await saveSnapshot(`calendar_${year}_${String(month0 + 1).padStart(2, '0')}`, currentHtml, {
      step: '5.1',
      year,
      month: month0 + 1,
      availableDates: calendarResult.dates,
    })
  }
  else {
    console.log('  已在日历页，使用当前页面')
    await saveSnapshot('calendar_current', currentHtml, {
      step: '5.1',
      note: '使用步骤4的日历页',
    })
  }
  
  const check1 = checkCalendarPage(currentHtml)
  
  if (!check1.success) {
    console.log('\n❌ 子步骤5.1失败：未到达日历页')
    process.exit(1)
  }
  
  // 更新表单字段（从日历页提取）
  const parser = getPageParser()
  currentFields = parser.extractFormFields(currentHtml, 'frmAppointment').success 
    && parser.extractFormFields(currentHtml, 'frmAppointment').data 
    ? parser.extractFormFields(currentHtml, 'frmAppointment').data! 
    : currentFields
  
  // 子步骤5.2: 扫描未来70天内（如果当前月没有可用日期）
  console.log('\n子步骤5.2: 扫描日历（未来70天内）')
  console.log('─'.repeat(60))
  
  const allAvailableDates: string[] = []
  
  if (check1.availableDates.length === 0) {
    console.log('  当前月没有可用日期，开始扫描后续月份...')
    
    const today = new Date()
    const maxDate = new Date(today)
    maxDate.setDate(today.getDate() + 70) // 未来70天
    
    console.log(`  扫描范围: ${today.toISOString().split('T')[0]} 至 ${maxDate.toISOString().split('T')[0]}`)
    
    let year = today.getFullYear()
    let month0 = today.getMonth()
    let scannedCount = 0
    const maxMonths = 3 // 最多扫描3个月（约90天，但会限制在70天内）
    
    // 扫描最多3个月，但限制在70天内
    for (let i = 0; i < maxMonths; i++) {
      // 计算要扫描的年月
      let scanYear = year
      let scanMonth0 = month0
      
      if (i === 0 && isAlreadyCalendar) {
        // 当前月已经在步骤5.1中获取，直接处理日期
        const filteredCurrentDates = check1.availableDates.filter((dateStr: string) => {
          try {
            const parts = dateStr.split('-').map(Number)
            if (parts.length !== 3) return false
            const [d, m, y] = parts
            const date = new Date(y, m - 1, d)
            return date <= maxDate && date >= today
          }
          catch {
            return false
          }
        })
        allAvailableDates.push(...filteredCurrentDates)
        if (filteredCurrentDates.length > 0) {
          console.log(`  当前月（已获取）: ${filteredCurrentDates.length} 个可用日期（在70天内）`)
        }
      }
      else {
        // 检查该月第一天是否还在70天范围内
        const monthFirstDay = new Date(scanYear, scanMonth0, 1)
        if (monthFirstDay > maxDate) {
          console.log(`  月份 ${scanYear}年${scanMonth0 + 1}月 已超过70天限制，停止扫描`)
          break
        }
        
        console.log(`\n  扫描 ${scanYear}年${scanMonth0 + 1}月...`)
        
        const monthResult = await getCalendarForMonth(session, currentFields, scanYear, scanMonth0)
        
        await saveSnapshot(`calendar_${scanYear}_${String(scanMonth0 + 1).padStart(2, '0')}`, monthResult.html, {
          step: `5.2.${i + 1}`,
          year: scanYear,
          month: scanMonth0 + 1,
          availableDates: monthResult.dates,
        })
        
        const monthDateCount = monthResult.dates.length
        console.log(`    ${scanYear}年${scanMonth0 + 1}月: ${monthDateCount} 个可用日期`)
        
        // 过滤掉超过70天的日期
        const filteredDates = monthResult.dates.filter((dateStr: string) => {
          try {
            const parts = dateStr.split('-').map(Number)
            if (parts.length !== 3) return false
            const [d, m, y] = parts
            const date = new Date(y, m - 1, d)
            return date <= maxDate && date >= today
          }
          catch {
            return false
          }
        })
        
        if (filteredDates.length < monthDateCount) {
          console.log(`    过滤后: ${filteredDates.length} 个可用日期（在70天内）`)
        }
        
        allAvailableDates.push(...filteredDates)
        scannedCount++
        
        // 如果找到可用日期，可以提前结束
        if (filteredDates.length > 0 && i < maxMonths - 1) {
          console.log(`    ✓ 找到可用日期，停止扫描`)
          break
        }
        
        // 更新表单字段（为下一月查询准备）
        const monthFields = parser.extractFormFields(monthResult.html, 'frmAppointment')
        if (monthFields.success && monthFields.data) {
          currentFields = { ...currentFields, ...monthFields.data }
        }
      }
      
      // 准备下一个月
      if (i < maxMonths - 1) {
        scanMonth0++
        if (scanMonth0 > 11) {
          scanMonth0 = 0
          scanYear++
        }
        
        // 检查下一个月第一天是否还在70天范围内
        const nextMonthFirstDay = new Date(scanYear, scanMonth0, 1)
        if (nextMonthFirstDay > maxDate) {
          console.log(`  下一个月（${scanYear}年${scanMonth0 + 1}月）已超过70天限制，停止扫描`)
          break
        }
        
        // 更新循环变量
        year = scanYear
        month0 = scanMonth0
      }
    }
    
    console.log(`  共扫描了 ${scannedCount} 个月份`)
  }
  else {
    console.log('  当前月有可用日期，检查是否在70天内')
    const today = new Date()
    const maxDate = new Date(today)
    maxDate.setDate(today.getDate() + 70)
    
    // 过滤当前月的日期，只保留70天内的
    const filteredCurrentDates = check1.availableDates.filter((dateStr: string) => {
      const [d, m, y] = dateStr.split('-').map(Number)
      const date = new Date(y, m - 1, d)
      return date <= maxDate && date >= today
    })
    
    if (filteredCurrentDates.length < check1.availableDates.length) {
      console.log(`  当前月: ${check1.availableDates.length} 个日期，${filteredCurrentDates.length} 个在70天内`)
    }
    
    allAvailableDates.push(...filteredCurrentDates)
  }
  
  // 去重并排序，并再次过滤确保在70天内
  const today = new Date()
  const maxDate = new Date(today)
  maxDate.setDate(today.getDate() + 70)
  
  const uniqueDates = [...new Set(allAvailableDates)]
    .map(dateStr => {
      const [d, m, y] = dateStr.split('-').map(Number)
      return { dateStr, date: new Date(y, m - 1, d) }
    })
    .filter(({ date }) => date <= maxDate && date >= today)
    .map(({ dateStr }) => dateStr)
    .sort()
  
  console.log(`\n📊 扫描结果:`)
  console.log(`  总计可用日期: ${uniqueDates.length} 个`)
  if (uniqueDates.length > 0) {
    console.log(`  可用日期列表: ${uniqueDates.slice(0, 20).join(', ')}${uniqueDates.length > 20 ? '...' : ''}`)
  }
  
  console.log('\n✓ 步骤5成功：日历扫描完成')
  console.log(`\n📁 快照目录: ${SNAPSHOT_DIR}`)
}

testStep5().catch((error) => {
  console.error('\n❌ 测试失败:', error)
  process.exit(1)
})

